package com.alibaba.nacos.config.server.jpa.repository;

import java.time.LocalDateTime;
import java.util.List;

import com.alibaba.nacos.config.server.jpa.entity.ConfigInfoEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/**
 * @author
 * @date 2020-03-08 23:31
 */
@Repository
public interface ConfigInfoRepository extends BaseRepository<ConfigInfoEntity, Long> {

    Page<ConfigInfoEntity> findByTenantIdLike(String tenantId, Pageable pageable);

    Page<ConfigInfoEntity> findByAppNameAndTenantIdLike(String appName, String tenantId, Pageable pageable);

    int countByTenantIdLike(String tenantId);

    Page<ConfigInfoEntity> findByTenantIdAndDataId(String tenantId, String dataId, Pageable pageable);

    Page<ConfigInfoEntity> findByTenantIdAndDataIdAndAppName(String tenantId, String dataId,
                                                             String appName, Pageable pageable);

    Page<ConfigInfoEntity> findByTenantIdAndGroupId(String tenantId, String groupId, Pageable pageable);

    Page<ConfigInfoEntity> findByTenantIdAndGroupIdAndAppName(String tenantId, String groupId,String appName, Pageable pageable);

    List<ConfigInfoEntity> findByTenantIdAndGroupIdAndAppNameAndDataIdLike(
        String tenantId, String groupId, String appName, String dataId);

    List<ConfigInfoEntity> findByGmtModifiedBetween(LocalDateTime start, LocalDateTime end);

    ConfigInfoEntity findByDataIdAndGroupIdAndTenantId(String dataId, String groupId, String tenantId);

    ConfigInfoEntity findByDataIdAndGroupIdAndTenantIdAndAppName(
        String dataId, String groupId, String tenantId, String appName);


    @Query("select ci from ConfigInfoEntity ci " +
        "left join ConfigTagsRelationEntity ctr on (ctr.id = ci.id) " +
        "where " +
        "ci.dataId = :dataId and ci.groupId = :groupId " +
        "and ci.tenantId = :tenantId and ctr.tagName in :tagNames")
    ConfigInfoEntity findOne(String dataId, String groupId,
                             String tenantId, List<String> tagNames);


    @Query("select ci from ConfigInfoEntity ci " +
        "left join ConfigTagsRelationEntity ctr on (ctr.id = ci.id) " +
        "where " +
        "ci.dataId = :dataId and ci.groupId = :groupId " +
        "and ci.tenantId = :tenantId and ctr.tagName in :tagNames " +
        "and ci.appName = :appName")
    ConfigInfoEntity findOne(String dataId, String groupId,
                             String tenantId, List<String> tagNames, String appName);

    @Query("select ci from ConfigInfoEntity ci " +
        "left join ConfigTagsRelationEntity ctr on (ctr.id = ci.id) " +
        "where " +
        "ci.tenantId = :tenantId and ctr.tagName in :tagNames ")
    Page<ConfigInfoEntity> findByTenantIdAndTagNames(String tenantId, List<String> tagNames, Pageable pageable);

    @Query("select ci from ConfigInfoEntity ci " +
        "left join ConfigTagsRelationEntity ctr on (ctr.id = ci.id) " +
        "where " +
        "ci.tenantId = :tenantId and ci.appName = :appName and ctr.tagName in :tagNames ")
    Page<ConfigInfoEntity> findByTenantIdAndAppNameAndTagNames(String tenantId, String appName,
                                                               List<String> tagNames, Pageable pageable);

    List<ConfigInfoEntity> findAllByGroupIdAndTenantIdAndDataIdIn(String groupId, String tenantId, List<String> dataIds);

    @Query("select ci from ConfigInfoEntity ci " +
        "left join ConfigTagsRelationEntity ctr on (ctr.id = ci.id) " +
        "where " +
        "ci.tenantId = :tenantId " +
        "and ci.dataId = :dataId " +
        "and ctr.tagName in :tagNames ")
    Page<ConfigInfoEntity> findByTenantIdAndDataIdAndTagNames(String tenantId, String dataId,
                                                               List<String> tagNames, Pageable pageable);

    @Query("SELECT max(id) FROM ConfigInfoEntity")
    Long findMaxId();

    @Query("select ci from ConfigInfoEntity ci " +
        "left join ConfigTagsRelationEntity ctr on (ctr.id = ci.id) " +
        "where " +
        "ci.tenantId = :tenantId " +
        "and ci.dataId = :dataId " +
        "and ci.appName = :appName " +
        "and ctr.tagName in :tagNames ")
    Page<ConfigInfoEntity> findByTenantIdAndDataIdAndAppNameAndTagNames(String tenantId, String dataId,
                                                              String appName,List<String> tagNames, Pageable pageable);

    @Query("select distinct ci.groupId from ConfigInfoEntity ci where ci.tenantId = ''")
    List<String> findGroupIds(Pageable pageable);

    @Query("select distinct ci.tenantId from ConfigInfoEntity ci where ci.tenantId <> ''")
    List<String> findTenantIds(Pageable pageable);

    @Modifying
    void deleteByIdIn(List<Long> ids);

    @Modifying
    void deleteByDataIdAndGroupIdAndTenantId(String dataId, String groupId, String tenantId);

    ConfigInfoEntity findByDataIdAndGroupIdAndTenantIdAndGmtModified(
        String dataId, String groupId, String tenantId, LocalDateTime gmtModified);
}
